/*
 * Server.cpp
 *
 *  Created on: 23.06.2012
 *      Author: sebastian
 */



#include "Server.h"

#include "../utils/utils.h"
#include <unistd.h> //for sleep
#include <iostream>
#include <errno.h>
#include "../HtmlWrapper.h"


#include <stdio.h>
#include <stdlib.h>

#include "../Game.h"


using namespace std;

Server::Server(int PORT) {
	memset(&bindAddr_, 0, sizeof(struct sockaddr_in));
	bindAddr_.sin_family = AF_INET;
	bindAddr_.sin_port = htons(PORT);

	bindAddr_.sin_addr.s_addr = INADDR_ANY;

	isRunning_ = false;
	thread_ = 0L;

	serverSocket_ = -1;

}

bool Server::start() {
	serverSocket_ = socket(AF_INET, SOCK_STREAM, 0);
		if (serverSocket_ == -1) {
			mLog("couldn't initialize server socket", LT_ERROR);
		}

		if (bind(serverSocket_, (struct sockaddr *) &bindAddr_, sizeof(bindAddr_)) == -1) {
			mLog("couldn't bind!", LT_ERROR);
			return false;
		}

		mLog("successfully created binding");


		isRunning_ = true;

		mLog("creating server thread....");
		pthread_create(&thread_,
				NULL,
				Server::run,
				(void*) this);

		return true;
}

void *Server::run(void *s) {
	Server* server = (Server*) s;
	listen(server->serverSocket_, 4);
		while (server->isRunning_) {
			server->tryAccept();
		}

		server->unBind();
		return NULL;
}

void Server::tryAccept() {
	sockaddr_in client_addr; //XXX TODO: generate not in loop and also genearte size of not in loop!
	socklen_t addrlen = sizeof(client_addr);
	int c = accept(serverSocket_, (struct sockaddr *) &client_addr, &addrlen);
	if (c == -1) {
		mLog("In socket "+intToStr(serverSocket_)+" while accepting", LT_ERROR);
		mLog("errno: "+ intToStr(errno));
		usleep(1000000);
	} else {
		char request[5000];
		int amount = read(c, request, sizeof(request));
		//set last byte to 0...
		request[amount] = 0;

		char client_addr_str[16];
		inet_ntop(AF_INET, &(client_addr.sin_addr), client_addr_str, 16);


		string msg = HtmlWrapper::processRequest(request, client_addr_str);

		//cout << "sending...\n" << msg.c_str();//only for Debugging reasons....

		unsigned int sentBytes = send(c, msg.c_str(), msg.length(), 0);
		if (sentBytes != msg.length()) //this should handle sent bytes...
			mLog("couldn't send all  bytes to client!", LT_ERROR);

	}
	close(c);

}


bool Server::stop() {
	isRunning_ = false;
	return true;
}

bool Server::unBind() {
	close(serverSocket_);
	return true;
}

Server::~Server() {
	// TODO Auto-generated destructor stub
	unBind();
}

string Server::generateNormalHeader(int bodyLen) {
	DmLog("generating normal header");
	return "HTTP/1.0 200 OK\nContent-Type: text/html\nContent-Length: " + intToStr(bodyLen);
}
